import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import lombok.Cleanup;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.ss.usermodel.*;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Objects;

/**
 * All rights Reserved, Designed By www.maihaoche.com
 *
 * @Package PACKAGE_NAME
 * @author: 皮皮（pipi@maihaoche.com）
 * @date: 2019/12/12 12:53 PM
 * @Copyright: 2017-2020 www.maihaoche.com Inc. All rights reserved.
 * 注意：本内容仅限于卖好车内部传阅，禁止外泄以及用于其他的商业目
 */
public class FileUtil {


    public <T> List<T> analysisExcel(String urlStr, Class<T> clazz, boolean isHaveHead) {
        try {
            URL url = new URL(urlStr);
            URLConnection uc = url.openConnection();
            @Cleanup InputStream inputStream = uc.getInputStream();
            return analysisExcel(inputStream, clazz, isHaveHead);
        } catch (GolfServiceException e) {
            throw e;
        } catch (Exception e) {
            throw new GolfServiceException(GolfErrorCodeEnum.EXCEPTION.getErrCode(), "解析Excel失败", e);
        }
    }


    public <T> List<T> analysisExcel(InputStream inputStream, Class<T> clazz, boolean isHaveHead) {
        try {
            Workbook workbook = WorkbookFactory.create(inputStream);
            Sheet sheet = workbook.getSheetAt(0);
            int firstRowNum = sheet.getFirstRowNum();
            int lastRowNum = sheet.getLastRowNum();
            firstRowNum = isHaveHead ? firstRowNum + 1 : firstRowNum;
            int rows = lastRowNum - firstRowNum;
            if (rows < 0) {
                return CollUtil.newArrayList();
            }
            List<T> excelData = CollUtil.newArrayList();

            Field[] fields = clazz.getDeclaredFields();
            List<Field> fieldList = CollUtil.newArrayList();
            for (Field field : fields) {
                if (field.isAnnotationPresent(ExcelImport.class)) {
                    fieldList.add(field);
                }
            }

            //第一条数据是表头不需要取
            for (int i = firstRowNum; i <= lastRowNum; i++) {
                Row row = sheet.getRow(i);
                if ( ExcelUtil.isRowEmpty(row)) {
                    continue;
                }
                T obj = clazz.newInstance();
                for (Field field : fieldList) {
                    ExcelImport excelImport = field.getAnnotation(ExcelImport.class);
                    int column = excelImport.column();
                    Cell cell = row.getCell(column);
                    if (Objects.isNull(cell)) {
                        continue;
                    }
                    Object value = null;
                    int cellType = cell.getCellType();
                    if (excelImport.isDate()) {
                        if (cellType == Cell.CELL_TYPE_NUMERIC) {
                            if (HSSFDateUtil.isCellDateFormatted(cell)) {
                                value = cell.getDateCellValue();
                            }
                        } else {
                            value = ExcelUtil.getCellString(cell);
                            value = DateUtil.parse(value.toString(), excelImport.datePatten());
                        }
                    }  else if (Cell.CELL_TYPE_STRING == excelImport.type()) {
                        value = ExcelUtil.getCellString(cell);
                    } else {
                        value = ExcelUtil.cellConvertToNumber(cell);
                        if (!excelImport.isPrice()) {
                            if (field.getType().equals(Integer.class)) {
                                value = Integer.valueOf(value.toString());
                            } else if (field.getType().equals(Long.class)) {
                                value = Long.valueOf(value.toString());
                            }
                        }
                    }

                    if (excelImport.isPrice()) {
                        value = PriceUtil.convertPriceYuan(value.toString());
                    }
                    String fieldName = field.getName();
                    Method method = buildSetMethod(clazz, fieldName, field.getType());
                    method.invoke(obj, value);
                }
                excelData.add(obj);
            }
            return excelData;
        } catch (Exception e) {
            throw new GolfServiceException(GolfErrorCodeEnum.ANALYSIS_FILE_FAIL.getErrCode(), "解析Excel失败", e);
        } finally {
            if (Objects.nonNull(inputStream)) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    private Method buildSetMethod(Class<?> clazz, String fieldName, Class<?>... params) throws NoSuchMethodException {
        String methodName = "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
        return clazz.getMethod(methodName, params);

    }
}
